!function(){
	"use strict";
	var Touch = {};
	$.extend(Touch,{
		callbackListKey: 'touchEventCallbackList',
		eventName: "ontouchend" in document ? {start: 'touchstart', move: 'touchmove', end: 'touchend'} : {start: 'mousedown', move: 'mousemove', end: 'mouseup'},
		on: function(dom, etype, callback){
			if(typeof(Touch['on'+etype])==="undefined") return false;
			for (var i = 0,args=[]; i < arguments.length; i++) {
				args.push(arguments[i])
			}
			args.splice(1,1);
			Touch['on'+etype].apply(Touch, args);
		},
		off: function(dom, etype){
			if(typeof(Touch['on'+etype])==="undefined") return false;
			var k = Touch.callbackListKey;
			dom[k] = dom[k] || [];
			dom[k][etype] = dom[k][etype] || [];
			for(;dom[k][etype].length;){
				dom.removeEventListener(Touch.eventName.start,dom[k][etype][0]);
				dom.removeEventListener(Touch.eventName.move,dom[k][etype][0]);
				dom.removeEventListener(Touch.eventName.end,dom[k][etype][0]);
				dom[k][etype].splice(0,1);
			}
		},
		//长按
		onlong: function(dom, callback, time){
	        time = time || 500;
			function ac(){
	            if(window.event.changedTouches && window.event.changedTouches.length !== 1) return;
	            var xy0 = $.eventOffsetScreen();
	            var th = setTimeout(function(){
	                typeof(callback)==="function" && callback.call(dom);
	                dom.removeEventListener(Touch.eventName.end, tout);
	                dom.removeEventListener(Touch.eventName.move, tout);
	            }, time);
	            function tout(){
	            	var xy1 = $.eventOffsetScreen();
	                if(window.event.type === Touch.eventName.end || Math.abs(xy1.x-xy0.x)>5 || Math.abs(xy1.y-xy0.y)>5){
	                    th && clearTimeout(th);
	                    dom.removeEventListener(Touch.eventName.end, tout);
	                    dom.removeEventListener(Touch.eventName.move, tout);
	                }
	            }
	            dom.addEventListener(Touch.eventName.end, tout);
	            dom.addEventListener(Touch.eventName.move, tout);
			}
			dom.addEventListener(Touch.eventName.start,ac);
	        registry(dom,ac,'long');
		},
		//回调函数传入{type,x,y}
		onchange: function(dom, callback){
			function ac(){
	            if(window.event.changedTouches && window.event.changedTouches.length !== 1) return;
	            var xy = $.eventOffsetScreen();
	            for (var name in Touch.eventName) {
	                if(window.event.type === Touch.eventName[name]){
	                    if(name === 'start'){
	                    	dom.addEventListener(Touch.eventName.end, ac);
	            			dom.addEventListener(Touch.eventName.move, ac);
	                    }else if(name === 'end'){
	                    	dom.removeEventListener(Touch.eventName.end, ac);
	                    	dom.removeEventListener(Touch.eventName.move, ac);
	                    }
	                    callback.call(dom,{type:name,x:xy.x,y:xy.y});
	                    break;
	                }
	            }
			}
			dom.addEventListener(Touch.eventName.start,ac);
			registry(dom,ac,'change');
		},
		//多点移动
		onpoints: function(dom, callback, num){
			num = num || 1;
			function ac(){
				if(!window.event.changedTouches) return;
				for (var name in Touch.eventName) {
	                if(window.event.type === Touch.eventName[name]){
	                    if(name === 'start' && window.event.touches.length === num){
	                    	dom.addEventListener(Touch.eventName.end, ac);
	            			dom.addEventListener(Touch.eventName.move, ac);
	                    }else if(name === 'end'){
	                    	dom.removeEventListener(Touch.eventName.end, ac);
	                    	dom.removeEventListener(Touch.eventName.move, ac);
	                    }else if(name === 'move'){
	                    	var xys = $.eventOffsetScreen();
	                    	callback.call(dom,xys);
	                    }
	                    break;
	                }
	            }
			}
			dom.addEventListener(Touch.eventName.start,ac);
			registry(dom,ac,'points');
		}
	})
	//注册已绑定事件的回调函数，便于移除
	function registry(dom,callback,etype){
		var k = Touch.callbackListKey;
        dom[k] = dom[k] || [];
		dom[k][etype] = dom[k][etype] || [];
		dom[k][etype].push(callback);
	}
	
	$.fn.extend({
		touchOn: function(etype, callback){
			for (var i = 0,args=[]; i < arguments.length; i++) {
				args.push(arguments[i])
			}
			this.forEach(function(dom){
				args.unshift(dom);
				Touch.on.apply(Touch, args);
				args.splice(0,1);
            })
		},
		touchOff: function(etype){
			this.forEach(function(dom){
				Touch.off(dom, etype);
            })
		}
	})
	$.Touch = Touch;
}()
